<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta
      name="keywords"
      content="HTML,CSS,HTML5,CSS3,ES6,JavaScript,Vue,Vue.js,TS,TypeScript,webpack,node.js,git,npm,前端,全栈,Web开发"
    />
    <meta
      name="description"
      content="一位Web开发工程师的学习、工作笔记-星之痕。
    内容涵盖：HTML,CSS,HTML5,CSS3,ES6,JavaScript,Vue,Vue.js,TS,TypeScript,前端,全栈,Web开发……等"
    />
    <title>vue组件-Vue.js 笔记-星之痕</title>
    <link rel="stylesheet" href="./css/global.css" />
  </head>

  <body>
    <div id="app">
      <!-- 调用组件 -->
      <v-note :title="title" :messages="messages"></v-note>
      <v-comp
        :c-info="info"
        @emit-click="alterData"
        @altersth-click="alterSth"
      ></v-comp>
      <h2>{{fullName}}</h2>
      <h2>{{info}}</h2>
      <h2>{{sthData}}</h2>
      <button class="btnClick" @click="btnClick">按钮</button>
    </div>

    <!-- 自定义组件模板 -->
    <template id="comp">
      <div>
        <h2>{{msg}}</h2>
        <h2>{{cInfo}}</h2>
        <h2>{{cfullName}}</h2>

        <button class="btn1Click" @click="btn1Click">按钮</button>
        <button class="btn2Click" @click="btn2Click">
          emit按钮 修改关联数据
        </button>
        <button class="btn3Click" @click="btn3Click">
          emit按钮 修改无关联数据
        </button>
      </div>
    </template>

    <!-- 组件模板 -->
    <template id="note">
      <div>
        <h2>{{title}}</h2>
        <ul>
          <li v-html="msg" v-for="msg in messages"></li>
        </ul>
      </div>
    </template>

    <script src="js/vue.js"></script>
    <script>
      // 自定义组件
      const vComp = {
        template: "#comp",
        data() {
          return {
            msg: "这是一个子组件",
          };
        },
        props: {
          cInfo: {
            default() {
              return {};
            },
          },
        },
        computed: {
          cfullName() {
            console.log("child computed");
            return "child fullName";
          },
        },
        created() {
          console.log("child created");
        },
        mounted() {
          console.log("child mounted");
        },
        beforeUpdate() {
          console.log("child beforeUpdate");
        },
        updated() {
          console.log("child updated");
        },
        methods: {
          btn1Click() {
            this.msg = "child data changed";
          },
          btn2Click() {
            this.$emit("emit-click");
          },
          btn3Click() {
            this.$emit("altersth-click");
          },
        },
      };

      // 笔记列表组件
      const vNote = {
        template: "#note",
        props: {
          title: String,
          messages: {
            type: Array,
            default() {
              return [];
            },
          },
        },
      };

      const app = new Vue({
        el: "#app",
        data: {
          title: "vue 父子组件生命周期函数执行顺序",
          messages: [
            `首先，不管是在哪个组件，created函数会先于mounted函数执行`,
            `如果组件内有computed，computed会紧跟着created执行`,
            `在父组件的computed,mounted之间会执行子组件的生命周期函数`,
            `等子组件执行完才会执行父组件的mounted函数，将子组件挂载到vue实例上，此时DOM已基本渲染完，
          但不能保证所有子组件，图片等资源都已加载完毕`,
            `如果想获取数据更新后的DOM，应该使用this.$nextTick()`,
            `updated函数执行顺序，当子组件内部使用了父组件的数据时，如果父组件的相关数据发生改变，
          子组件的updated和父组件的updated会一起执行，子组件在前，父组件在后`,
            `如果有beforeUpdate,在父组件beforeUpdate&updated之间执行子组件的beforeUpdate&updated;
          不管是父组件修改传递给子组件的数据，还是子组件发射事件修改与父组件关联的数据都是这样执行`,
            `子组件的emit事件提交给父组件修改的是与子组件无关的数据，则不会触发子组件的update事件`,
          ],
          info: "this is a message",
          sthData: "test data",
        },
        components: {
          vNote,
          vComp,
        },
        computed: {
          fullName() {
            console.log("parent computed");
            return "parent fullName";
          },
        },
        created() {
          console.log("parent created");
        },
        mounted() {
          console.log("parent mounted");
        },
        beforeUpdate() {
          console.log("parent beforeUpdate");
        },
        updated() {
          console.log("parent updated");
        },
        destroyed() {
          console.log("destroyed");
        },
        methods: {
          btnClick() {
            this.info = "data changed!";
          },
          alterData() {
            this.info = "parent Data changed";
          },
          alterSth() {
            this.sthData = "parent someData changed";
          },
        },
      });
    </script>
  </body>
</html>
